iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0
Modern Web

前進React 生態系 : 技術應用與概念解析系列 第 29

Day 29 - React Hooks 原理解析

  • 分享至 

  • xImage
  •  

React Hooks 的運作機制是建立在 React Fiber 架構之上,所有的 Hook 狀態會以 linked list 的方式儲存。fiber 中的 memorizedState 就是用來保存 hooks 資料的地方,不同的 Hook 會儲存不同的資料,但基本的儲存和處理流程是類似的。

這樣的 linked list 結構確保每個 component 渲染時,React 能夠依照 Hook 的調用順序來讀取和更新對應的狀態。React 在初次渲染和後續更新過程中會執行不同的邏輯來處理 Hook。

初次渲染過程

當一個組件第一次渲染時,React 會創建一條新的 linked list 來儲存每個 Hook 的狀態。每次呼叫一個 Hook,React 會創建對應的 Hook 狀態物件,並依次將它們連接起來。

React 透過 workInProgressHook 這個指標來追蹤當前處理的 Hook。每當你呼叫一個新的 Hook,這個指標會移動到下一個 Hook 狀態,並將新 Hook 串在 linked list 上,這樣 React 可以依序處理每個 Hook 的邏輯。

Hook 狀態物件的屬性有這些:

memorizedState: 根據不同類型的 hook 保存對應的資料或狀態
baseState: 本次更新前 Fiber 節點的狀態
baseQueue: 在此次更新前的狀態更新隊列
queue: 儲存本次更新中待處理的狀態更新隊列
next : 只向下一個 Hook 物件

後續更新過程

在組件後續更新時,React 不會重新創建 Hook 的 linked list,而是根據上一次渲染的內容進行更新。React 會使用一個指標來追蹤每個 Hook,逐一更新它們的狀態。

  • 如果 Hook 沒有變更,React 會直接重用之前的狀態。
  • 如果 Hook 發生變更(例如 useState 中的 state 更新),React 會為這個 Hook 創建新的狀態物件,並在 linked list 中更新它的對應的位置。

為什麼 Hook 只能在頂層呼叫?不能在條件式中使用?

React 透過 Hook 的調用順序來追蹤每個 component 的 狀態。當 Hook 被放入條件判斷中,會造成每次渲染時 Hook 呼叫順序的不一致,進而導致 React 錯誤管理這些狀態。例如,下面的程式碼:

function Component() {
  const [state1, setState1] = useState(false); //狀態1
  if (state1) {
    const [state3, setState3] = useState(0); //狀態3
  }
  const [state2, setState2] = useState(0); //狀態2

  return (
    <div>
      <button onClick={() => setState1(true)}>Click</button>
      <p>{state1}</p>
      <p>{state2}</p>
    </div>
  );
}

當 state1 是 false : 只會調用兩個 Hook(state1 和 state2),
當 state1 是 true : useState 會多出一個新的 Hook(state3),會把 state2 的狀態賦值給 state3。

為什麼一定要在 React Function Component 或 Custom Hook 中使用?

Hook 的調用和更新都依賴於 fiber 的存在。如果在普通的 function 中使用 Hook,React 無法將這些 Hook 對應到 fiber 上的正確位置,這會導致無法正確追蹤狀態並引發錯誤。

參考資料:

https://www.youtube.com/watch?v=cxbVN1F-aag
https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e
https://juejin.cn/post/6968820472431509535
https://segmentfault.com/a/1190000039076330


上一篇
Day 28 - React Server Components 原理解析
下一篇
Day 30 - 文章總結 & 文章大綱 & 完賽感言
系列文
前進React 生態系 : 技術應用與概念解析30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言